//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Security.Permissions;
using System.Xml.Xsl;
namespace DotNetNuke.Common.Utilities
{
    public class XmlUtils
    {
        public static void AppendElement(ref XmlDocument objDoc, XmlNode objNode, string attName, string attValue, bool includeIfEmpty)
        {
            AppendElement(ref objDoc, objNode, attName, attValue, includeIfEmpty, false);
        }
        public static void AppendElement(ref XmlDocument objDoc, XmlNode objNode, string attName, string attValue, bool includeIfEmpty, bool CDATA)
        {
            if (String.IsNullOrEmpty(attValue) && !includeIfEmpty)
            {
                return;
            }
            if (CDATA)
            {
                objNode.AppendChild(CreateCDataElement(objDoc, attName, attValue));
            }
            else
            {
                objNode.AppendChild(CreateElement(objDoc, attName, attValue));
            }
        }
        public static XmlAttribute CreateAttribute(XmlDocument objDoc, string attName, string attValue)
        {
            XmlAttribute attribute = objDoc.CreateAttribute(attName);
            attribute.Value = attValue;
            return attribute;
        }
        public static void CreateAttribute(XmlDocument objDoc, XmlNode objNode, string attName, string attValue)
        {
            XmlAttribute attribute = objDoc.CreateAttribute(attName);
            attribute.Value = attValue;
            objNode.Attributes.Append(attribute);
        }

        [Obsolete("Removed in DotNetNuke 5.5")]
        public static XmlElement CreateElement(XmlDocument objDoc, string NodeName)
        {
            return objDoc.CreateElement(NodeName);
        }
        public static XmlElement CreateElement(XmlDocument objDoc, string NodeName, string NodeValue)
        {
            XmlElement element = objDoc.CreateElement(NodeName);
            element.InnerText = NodeValue;
            return element;
        }
        public static XmlElement CreateCDataElement(XmlDocument objDoc, string NodeName, string NodeValue)
        {
            XmlElement element = objDoc.CreateElement(NodeName);
            element.AppendChild(objDoc.CreateCDataSection(NodeValue));
            return element;
        }

        [Obsolete("Replaced in DotNetNuke 5.5 with CBO.DeserializeObject")]
        public static object Deserialize(string xmlObject, System.Type type)
        {
            XmlSerializer ser = new XmlSerializer(type);
            StringReader sr = new StringReader(xmlObject);
            object obj = ser.Deserialize(sr);
            sr.Close();
            return obj;
        }
        public static object Deserialize(Stream objStream, System.Type type)
        {
            object obj = Activator.CreateInstance(type);
            Dictionary<int, TabInfo> tabDic = obj as Dictionary<int, TabInfo>;
            if (tabDic != null)
            {
                obj = DeSerializeDictionary<TabInfo>(objStream, "dictionary");
                return obj;
            }
            Dictionary<int, ModuleInfo> moduleDic = obj as Dictionary<int, ModuleInfo>;
            if (moduleDic != null)
            {
                obj = DeSerializeDictionary<ModuleInfo>(objStream, "dictionary");
                return obj;
            }
            Dictionary<int, TabPermissionCollection> tabPermDic = obj as Dictionary<int, TabPermissionCollection>;
            if (tabPermDic != null)
            {
                obj = DeSerializeDictionary<TabPermissionCollection>(objStream, "dictionary");
                return obj;
            }
            Dictionary<int, ModulePermissionCollection> modPermDic = obj as Dictionary<int, ModulePermissionCollection>;
            if (modPermDic != null)
            {
                obj = DeSerializeDictionary<ModulePermissionCollection>(objStream, "dictionary");
                return obj;
            }
            XmlSerializer serializer = new XmlSerializer(type);
            TextReader tr = new StreamReader(objStream);
            obj = serializer.Deserialize(tr);
            tr.Close();
            return obj;
        }
        public static Dictionary<int, TValue> DeSerializeDictionary<TValue>(Stream objStream, string rootname)
        {
            Dictionary<int, TValue> objDictionary = null;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(objStream);
            objDictionary = new Dictionary<int, TValue>();
            foreach (XmlElement xmlItem in xmlDoc.SelectNodes(rootname + "/item"))
            {
                int key = Convert.ToInt32(xmlItem.GetAttribute("key"));
                string typeName = xmlItem.GetAttribute("type");
                TValue objValue = Activator.CreateInstance<TValue>();
                XmlSerializer xser = new XmlSerializer(objValue.GetType());
                XmlTextReader reader = new XmlTextReader(new StringReader(xmlItem.InnerXml));
                objDictionary.Add(key, (TValue)xser.Deserialize(reader));
            }
            return objDictionary;
        }
        public static Hashtable DeSerializeHashtable(string xmlSource, string rootname)
        {
            Hashtable objHashTable;
            if (!String.IsNullOrEmpty(xmlSource))
            {
                objHashTable = new Hashtable();
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(xmlSource);
                foreach (XmlElement xmlItem in xmlDoc.SelectNodes(rootname + "/item"))
                {
                    string key = xmlItem.GetAttribute("key");
                    string typeName = xmlItem.GetAttribute("type");
                    XmlSerializer xser = new XmlSerializer(Type.GetType(typeName));
                    XmlTextReader reader = new XmlTextReader(new StringReader(xmlItem.InnerXml));
                    objHashTable.Add(key, xser.Deserialize(reader));
                }
            }
            else
            {
                objHashTable = new Hashtable();
            }
            return objHashTable;
        }
        public static string GetAttributeValue(XPathNavigator nav, string AttributeName)
        {
            return nav.GetAttribute(AttributeName, "");
        }
        public static int GetAttributeValueAsInteger(XPathNavigator nav, string AttributeName, int DefaultValue)
        {
            int intValue = DefaultValue;
            string strValue = GetAttributeValue(nav, AttributeName);
            if (!string.IsNullOrEmpty(strValue))
            {
                intValue = Convert.ToInt32(strValue);
            }
            return intValue;
        }
        public static string GetNodeValue(XPathNavigator nav, string path)
        {
            string strValue = Null.NullString;
            XPathNavigator elementNav = nav.SelectSingleNode(path);
            if (elementNav != null)
            {
                strValue = elementNav.Value;
            }
            return strValue;
        }
        public static string GetNodeValue(XmlNode objNode, string NodeName, string DefaultValue)
        {
            string strValue = DefaultValue;
            if ((objNode[NodeName] != null))
            {
                strValue = objNode[NodeName].InnerText;
                if (String.IsNullOrEmpty(strValue) && !String.IsNullOrEmpty(DefaultValue))
                {
                    strValue = DefaultValue;
                }
            }
            return strValue;
        }
        public static bool GetNodeValueBoolean(XmlNode objNode, string NodeName)
        {
            return GetNodeValueBoolean(objNode, NodeName, false);
        }
        public static bool GetNodeValueBoolean(XmlNode objNode, string NodeName, bool DefaultValue)
        {
            bool bValue = DefaultValue;
            if ((objNode[NodeName] != null))
            {
                string strValue = objNode[NodeName].InnerText;
                if (!string.IsNullOrEmpty(strValue))
                {
                    bValue = Convert.ToBoolean(strValue);
                }
            }
            return bValue;
        }
        public static DateTime GetNodeValueDate(XmlNode objNode, string NodeName, DateTime DefaultValue)
        {
            DateTime dateValue = DefaultValue;
            if ((objNode[NodeName] != null))
            {
                string strValue = objNode[NodeName].InnerText;
                if (!string.IsNullOrEmpty(strValue))
                {
                    dateValue = Convert.ToDateTime(strValue);
                    if (dateValue.Date.Equals(Null.NullDate.Date))
                    {
                        dateValue = Null.NullDate;
                    }
                }
            }
            return dateValue;
        }
        public static int GetNodeValueInt(XmlNode objNode, string NodeName)
        {
            return GetNodeValueInt(objNode, NodeName, 0);
        }
        public static int GetNodeValueInt(XmlNode objNode, string NodeName, int DefaultValue)
        {
            int intValue = DefaultValue;
            if ((objNode[NodeName] != null))
            {
                string strValue = objNode[NodeName].InnerText;
                if (!string.IsNullOrEmpty(strValue))
                {
                    intValue = Convert.ToInt32(strValue);
                }
            }
            return intValue;
        }
        public static float GetNodeValueSingle(XmlNode objNode, string NodeName)
        {
            return GetNodeValueSingle(objNode, NodeName, 0);
        }
        public static float GetNodeValueSingle(XmlNode objNode, string NodeName, float DefaultValue)
        {
            float sValue = DefaultValue;
            if ((objNode[NodeName] != null))
            {
                string strValue = objNode[NodeName].InnerText;
                if (!string.IsNullOrEmpty(strValue))
                {
                    sValue = Convert.ToSingle(strValue, System.Globalization.CultureInfo.InvariantCulture);
                }
            }
            return sValue;
        }
        public static XmlWriterSettings GetXmlWriterSettings(ConformanceLevel conformance)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.ConformanceLevel = conformance;
            settings.OmitXmlDeclaration = true;
            settings.Indent = true;
            return settings;
        }

        public static string SerializeDictionary(IDictionary Source, string rootName)
        {
            string strString;
            if (Source.Count != 0)
            {
                XmlSerializer xser;
                StringWriter sw;
                XmlDocument xmlDoc = new XmlDocument();
                XmlElement xmlRoot = xmlDoc.CreateElement(rootName);
                xmlDoc.AppendChild(xmlRoot);
                foreach (object key in Source.Keys)
                {
                    XmlElement xmlItem = xmlDoc.CreateElement("item");
                    xmlItem.SetAttribute("key", Convert.ToString(key));
                    xmlItem.SetAttribute("type", Source[key].GetType().AssemblyQualifiedName.ToString());
                    XmlDocument xmlObject = new XmlDocument();
                    xser = new XmlSerializer(Source[key].GetType());
                    sw = new StringWriter();
                    xser.Serialize(sw, Source[key]);
                    xmlObject.LoadXml(sw.ToString());
                    xmlItem.AppendChild(xmlDoc.ImportNode(xmlObject.DocumentElement, true));
                    xmlRoot.AppendChild(xmlItem);
                }
                strString = xmlDoc.OuterXml;
            }
            else
            {
                strString = "";
            }
            return strString;
        }

        public static void SerializeHashtable(Hashtable Hashtable, XmlDocument XmlDocument, XmlNode RootNode, string ElementName, string KeyField, string ValueField)
        {
            string sKey = null;
            string sOuterElementName = null;
            string sInnerElementName = null;
            XmlNode nodeSetting = default(XmlNode);
            XmlNode nodeSettings = default(XmlNode);
            XmlNode nodeSettingName = default(XmlNode);
            XmlNode nodeSettingValue = default(XmlNode);

            sOuterElementName = ElementName + "s";
            sInnerElementName = ElementName;

            nodeSettings = RootNode.AppendChild(XmlDocument.CreateElement(sOuterElementName));
            foreach (string sKey_loopVariable in Hashtable.Keys)
            {
                sKey = sKey_loopVariable;
                nodeSetting = nodeSettings.AppendChild(XmlDocument.CreateElement(sInnerElementName));
                nodeSettingName = nodeSetting.AppendChild(XmlDocument.CreateElement(KeyField));
                nodeSettingName.InnerText = sKey;
                nodeSettingValue = nodeSetting.AppendChild(XmlDocument.CreateElement(ValueField));
                nodeSettingValue.InnerText = Hashtable[sKey].ToString();
            }
        }


        public static void UpdateAttribute(XmlNode node, string attName, string attValue)
        {
            if ((node != null))
            {
                XmlAttribute attrib = node.Attributes[attName];
                attrib.InnerText = attValue;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Xml Encodes HTML
        /// </summary>
        /// <param name="HTML">The HTML to encode</param>
        /// <returns></returns>
        /// <history>
        ///		[cnurse]	09/29/2005	moved from Globals
        /// </history>
        /// -----------------------------------------------------------------------------
        public static string XMLEncode(string HTML)
        {
            return "<![CDATA[" + HTML + "]]>";
        }


        public static void XSLTransform(XmlDocument doc, ref StreamWriter writer, string xsltUrl)
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(xsltUrl);
            //Transform the file.
            xslt.Transform(doc, null, writer);
        }

        public static string Serialize(object obj)
        {
            string xmlObject = null;
            IDictionary dic = obj as IDictionary;
            if ((dic != null))
            {
                xmlObject = SerializeDictionary(dic, "dictionary");
            }
            else
            {
                XmlDocument xmlDoc = new XmlDocument();
                XmlSerializer xser = new XmlSerializer(obj.GetType());
                StringWriter sw = new StringWriter();

                xser.Serialize(sw, obj);

                xmlDoc.LoadXml(sw.GetStringBuilder().ToString());
                XmlNode xmlDocEl = xmlDoc.DocumentElement;
                xmlDocEl.Attributes.Remove(xmlDocEl.Attributes["xmlns:xsd"]);
                xmlDocEl.Attributes.Remove(xmlDocEl.Attributes["xmlns:xsi"]);

                xmlObject = xmlDocEl.OuterXml;
            }
            return xmlObject;
        }

        [Obsolete("This method is obsolete.")]
        public static XmlDocument GetXMLContent(string ContentUrl)
        {
            XmlDocument functionReturnValue = default(XmlDocument);
            //This function reads an Xml document via a Url and returns it as an XmlDocument object

            functionReturnValue = new XmlDocument();
            WebRequest req = WebRequest.Create(ContentUrl);
            WebResponse result = req.GetResponse();
            Stream ReceiveStream = result.GetResponseStream();
            XmlReader objXmlReader = new XmlTextReader(result.GetResponseStream());
            functionReturnValue.Load(objXmlReader);
            return functionReturnValue;

        }

    }
}
